<template>
  <div class="menu-management">
    <el-card style="height: 85vh;">
      <div>
        <!-- <vxe-button @click="expandAllEvent">展开所有</vxe-button>
        <vxe-button @click="clearExpandEvent">关闭所有</vxe-button> 
         <vxe-button status="primary" icon="vxe-icon-add" @click="editRow()">新增</vxe-button> -->
      </div>
      <vxe-grid
        v-bind="gridOptions"
        :data="flatMenuData"
        ref="gridRef"
        v-on="gridEvents"
        @checkbox-all="selectAllChangeEvent"
        @checkbox-change="selectChangeEvent"
      >
        <template #action="{ row }">
          <vxe-button
            v-for="btn in inTableButtons"
            :key="btn.code"
            size="small"
            :status="btn.status"
            mode="text"
            :icon="getButtonIcon(btn.code)"
            @click="
              handleRowAction(btn.code, row, {
                openEditPopup: editRow,
                addChildMenu: addChildMenu,
                removeRow: handleDelete,
              })
            "
            :content="btn.name"
          ></vxe-button>
        </template>
        <template #iconCell="{ row }">
          <i :class="row.icon"></i>
        </template>
        <template #typeCell="{ row }">
          <vxe-tag :status="typeStatusMap[row.type]">
            {{ typeLabelMap[row.type] }}
          </vxe-tag>
        </template>
      </vxe-grid>
      <vxe-modal
        v-model="showEditPopup"
        :title="form.id ? '编辑菜单' : '新建菜单'"
        width="50%"
        show-footer
      >
        <template #default>
          <vxe-form
            :data="form"
            :items="formItems"
            :rules="formRules"
            ref="formRef"
            title-align="right"
            title-width="100"
          >
            <!-- 可以自定义插槽 -->
          </vxe-form>
        </template>
        <template #footer>
          <vxe-button
            @click="showEditPopup = false"
            content="取消"
          ></vxe-button>
          <vxe-button
            status="primary"
            @click="confirmEvent"
            content="保存"
          ></vxe-button>
        </template>
      </vxe-modal>
    </el-card>
  </div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import { ElMessage } from "element-plus";
import VxeUI, { type VxeFormInstance } from "vxe-pc-ui";
import { useRoute } from "vue-router";
import type { MenuNode } from "@/types/menu";
import {
  queryTreeList,
  menuAdd,
  getDetailId,
  delEntityById,
  sysDict,
  menuHidden,
} from "@/api";
import { getPermissionsByRoute } from "@/utils/common";
import { permToButtons, splitButtonsByLocation } from "@/utils/permission";
import { useTableActions,setupToolbar } from "@/utils/useTableActions";
import type {
  VxeGridProps,
  VxeGridListeners,
  VxeGridInstance,
  VxeColumnPropTypes,
  VxeGridEvents,
} from "vxe-table";
const route = useRoute();
const Permission = ref<any[]>([]);
const selectedRows = ref<MenuNode[]>([]);
const selectedIcon = ref<string>("");
const btnDatas = ref<any[]>([]);
const dictData = ref<any[]>([]);
const inTableButtons = ref<any[]>([]);
// 菜单数据
const menuData = ref<MenuNode[]>([]);
const flatMenuData = computed(() => {
  return transformTreeToFlat(menuData.value);
});

const reloadMenuData = async (searchParams = {}) => {
  try {
    const data = await queryTreeList("menu", searchParams);
    if (Array.isArray(data)) {
      menuData.value = data;
      const flatData = transformTreeToFlat(data);
      gridOptions.data = flatData; 
       gridOptions.toolbarConfig = setupToolbar(Permission.value);
    } else {
      gridOptions.data = [];
    }
  } catch (err) {
    ElMessage.error("加载菜单数据失败");
    gridOptions.data = [];
  }
};
// 初始化数据
onMounted(async () => {
  try {
    // 按钮数据获取
    btnDatas.value = await getPermissionsByRoute(route.name);
    const permissions = route.meta.permission || [];
    const allButtons = permToButtons(permissions);
    const { toolbarButtons, inTableButtons: ops } =
      splitButtonsByLocation(allButtons);

    Permission.value = toolbarButtons;
    inTableButtons.value = ops; // 存入响应式变量
    await reloadMenuData();
    const dict = await sysDict({
      field: "type",
      value: "menu_type",
    });
    dictData.value = dict.childList;
  } catch (error) {
    ElMessage.error("加载菜单失败");
  }
});
const typeLabelMap = computed(() => {
  const map: Record<string, string> = {};
  dictData.value.forEach((item) => {
    map[item.value] = item.label;
  });
  return map;
});

const typeStatusMap = computed(() => {
  const map: Record<string, string> = {};
  dictData.value.forEach((item) => {
    map[item.value] = item.value === "0" ? "danger" : "info";
  });
  return map;
});

const transformTreeToFlat = (
  tree: MenuNode[],
  parent: MenuNode | null = null
): RowVO[] => {
  const result: RowVO[] = [];
  tree.forEach((node) => {
    const flatNode = {
      id: node.id,
      parentId: node.parentId ?? null,
      name: node.title,
      title: node.title,
      vueHref: node.vueHref,
      href: node.href,
      icon: node.icon,
      inOrOutTable: node.inOrOutTable,
      hidden: node.hidden == "0" ? true : false,
      type: node.type,
      vuePermission: node.vuePermission,
      sort: node.sort,
      createTime: node.createTime,
      children: node.children,
      remarks: node.remarks,
    };
    result.push(flatNode);
    if (node.children && node.children.length > 0) {
      result.push(...transformTreeToFlat(node.children, node));
    }
  });
  return result;
};

interface RowVO {
  id: number;
  parentId: number | null;
  name: string;
  title: string;
  type: boolean;
  size: number;
  date: string;
}
const flagCellRender = reactive<VxeColumnPropTypes.CellRender>({
  name: "VxeSwitch",
  props: {
    modelValue: ({ row }) => {
      return row.hidden !== "0" && row.hidden !== 0 && row.hidden !== false;
    },
    disabled: false,
  },
  events: {
    change: async ({ row }) => {
      const hiddenValue = row.hidden ? 0 : 1;
      try {
        const result = await menuHidden({
          id: row.id,
          value: hiddenValue,
        });
        if (result.code === 0) {
          ElMessage.success(result.message);
          await reloadMenuData();
        } else {
          ElMessage.error(result.message);
        }
      } catch (err) {
        ElMessage.error("请求失败");
      }
    },
  },
});
const gridRef = ref<VxeGridInstance<RowVO>>();
const gridOptions = reactive<
  VxeGridProps<RowVO> & {
    data: RowVO[];
  }
>({
  showOverflow: true,
  border: true,
  size: "mini",
  height: 1080,
  columnConfig: {
    resizable: true,
  },
  printConfig: {},
  importConfig: {},
  exportConfig: {},
  toolbarConfig: {
    buttons: [],
  },
  rowConfig: {
    isCurrent: true,
    isHover: true,
  },
  radioConfig: {
    labelField: "title",
    trigger: "row",
  },
  formConfig: {
    data: {
      title: "",
    },
    items: [
      { field: "title", title: "名称", itemRender: { name: "VxeInput" } },
      {
        itemRender: {
          name: "VxeButtonGroup",
          options: [
            { type: "submit", content: "搜索", status: "primary" },
            { type: "reset", content: "重置" },
          ],
        },
      },
    ],
  },
  treeConfig: {
    transform: true,
    rowField: "id",
    parentField: "parentId",
  },
  columns: [
    { type: "checkbox", width: 60 },
    {
      field: "title",
      title: "菜单名称",
      minWidth: 300,
      treeNode: true,
    },
    {
      field: "vueHref",
      title: "路径",
      minWidth: 160,
    },
    {
      field: "href",
      title: "路径",
      minWidth: 160,
    },
    {
      field: "icon",
      title: "图标",
      width: 120,
      slots: { default: "iconCell" },
    },
    {
      field: "vuePermission",
      title: "权限",
      minWidth: 140,
    },
    {
      field: "hidden",
      title: "是否显示",
      width: 100,
      cellRender: flagCellRender,
    },
    {
      field: "type",
      title: "类型",
      width: 80,
      slots: { default: "typeCell" },
    },
    {
      field: "sort",
      title: "排序",
      width: 80,
    },
    {
      field: "createTime",
      title: "创建时间",
      minWidth: 140,
    },
    { title: "操作", minWidth: 200, slots: { default: "action" } },
  ],
  data: [],
});

// 菜单表单
const form = ref({
  id: null as string | number | null,
  parentPath: [] as string[],
  parentId: null as string | number | null,
  title: "",
  vueHref: "",
  icon: "",
  inOrOutTable: 0,
  type: 0,
  vuePermission: "",
  sort: 0,
  remarks: "",
});
const formRef = ref<VxeFormInstance<RowVO>>();

// 根据 ID 在树中查找完整路径
const getNodePathById = (
  tree: MenuNode[],
  id: string,
  path: string[] = []
): string[] | null => {
  for (const node of tree) {
    const currentPath = [...path, node.id];
    if (node.id === id) return currentPath;
    if (node.children) {
      const result = getNodePathById(node.children, id, currentPath);
      if (result) return result;
    }
  }
  return null;
};

// 从树中删除节点（修改原数组）
const removeNodeById = (tree: MenuNode[], id: string): boolean => {
  for (let i = 0; i < tree.length; i++) {
    if (tree[i].id === id) {
      tree.splice(i, 1);
      return true;
    }
    if (tree[i].children) {
      if (removeNodeById(tree[i].children!, id)) {
        return true;
      }
    }
  }
  return false;
};

// 根据 ID 查找节点（用于编辑等）
const findNodeById = (tree: MenuNode[], id: string): MenuNode | null => {
  for (const node of tree) {
    if (node.id === id) return node;
    if (node.children) {
      const found = findNodeById(node.children, id);
      if (found) return found;
    }
  }
  return null;
};

const showEditPopup = ref(false);
interface TreeOption {
  value: string | number;
  label: string;
  children?: TreeOption[];
  disabled?: boolean;
}
// 判断 targetId 是否是 sourceId 的子节点（包含自身）
const isChildOrSelf = (
  nodes: MenuNode[],
  sourceId: string,
  targetId: string
): boolean => {
  for (const node of nodes) {
    if (node.id === targetId) return true;
    if (node.id === sourceId) continue;
    if (node.children) {
      if (isChildOrSelf(node.children, sourceId, targetId)) return true;
    }
  }
  return false;
};

// 构建带 disabled 的选项
const buildTreeSelectOptions = (
  nodes: MenuNode[],
  currentId?: string
): TreeOption[] => {
  return nodes.map((node) => ({
    value: node.id,
    label: node.title,
    disabled: currentId
      ? isChildOrSelf(menuData.value, currentId, node.id)
      : false,
    children:
      node.children && node.children.length > 0
        ? buildTreeSelectOptions(node.children, currentId)
        : undefined,
  }));
};

const formItems = computed(() => {
  if (!menuData.value || menuData.value.length === 0) return [];
  const typeOptions = dictData.value.map((item) => ({
    label: item.label,
    value: Number(item.value),
  }));
  return [
    {
      field: "parentId",
      title: "上级菜单",
      itemRender: {
        name: "VxeTreeSelect",
        options: buildTreeSelectOptions(menuData.value),
      },
      span: 12,
    },
    {
      field: "type",
      title: "类型",
      itemRender: {
        name: "VxeRadioGroup",
        options: typeOptions,
      },
      span: 12,
    },
    {
      field: "title",
      title: "名称",
      itemRender: {
        name: "VxeInput",
        props: { placeholder: "请输入名称" },
      },
      span: 12,
    },
    {
      field: "inOrOutTable",
      title: "表格内显示",
      itemRender: {
        name: "VxeRadioGroup",
        options: [
          { label: "是", value: 0 },
          { label: "否", value: 1 },
        ],
      },
      span: 12,
    },
    {
      field: "vueHref",
      title: "页面路径",
      itemRender: {
        name: "VxeInput",
        props: { placeholder: "如: /basic/size" },
      },
      span: 12,
    },
    {
      field: "vuePermission",
      title: "权限标识",
      itemRender: { name: "VxeInput", props: { placeholder: "如: user:add" } },
      span: 12,
    },
    {
      field: "sort",
      title: "排序",
      itemRender: { name: "VxeNumberInput", props: { min: 0, max: 999 } },
      span: 12,
    },
    {
      field: "icon",
      title: "图标",
      itemRender: {
        name: "VxeIconPicker",
        options: [
          "add",
          "add-sub", 
          "arrow-down",
          "arrow-double-left",
          "arrow-double-right",
          "arrow-left",
          "arrow-right",
          "arrow-up",
          "caret-down",
          "caret-right",
          "calendar",
          "setting",
          "flow-branch",
          "home",
          "home-fill",
          "setting-fill",
          "checkbox-checked-fill",
          "checkbox-indeterminate-fill",
          "checkbox-unchecked",
          "checkbox-unchecked-fill",
          "close",
          "copy",
          "chart-bar-y",
          "custom-column",
          "delete",
          "drag-handle",
          "download", 
          "edit",
          "empty",
          "end-page",
          "grouping",
          "error-circle-fill",
          "eye-fill",
          "eye-fill-close",
          "file",
          "file-excel",
          "file-image",
          "file-markdown",
          "file-pdf",
          "file-ppt",
          "file-word",
          "file-zip", 
          "fixed-left",
          "fixed-left-fill",
          "fixed-right",
          "fixed-right-fill",
          "fullscreen", 
          "home-page",
          "info-circle-fill",
          "layout", 
          "maximize",
          "menu",
          "minimize",
          "minus",
          "mobile",
          "no-drop",
          "pc",
          "print",
          "question-circle-fill",
          "radio-checked-fill",
          "radio-unchecked",
          "radio-unchecked-fill",
          "recover",
          "refresh",
          "repeat",
          "rotate-left",
          "rotate-right",
          "search",
          "search-zoom-in",
          "search-zoom-out",
          "sort",
          "spinner",
          "square",
          "square-minus",
          "square-plus",
          "square-plus-fill",
          "star",
          "star-fill",
          "swap", 
          "upload",
          "user",
          "user-fill",
        ],
        props: {
          vModel: form.value.icon, // 绑定表单字段
          clearable: true,
          placeholder: "请选择图标",
        },
        events: {
          change: (value: string, res) => {
            console.log(res.value);
            form.value.icon = typeof value === "object" ? res.value : value;
          },
        },
      },
      span: 12,
    },
    {
      field: "remarks",
      title: "备注",
      itemRender: {
        name: "VxeTextarea",
        props: {
          placeholder: `请输入`,
          autosize: { minRows: 2, maxRows: 4 },
        },
      },
      span: 12,
    },
  ];
});
const formRules = ref({
  title: [{ required: true, message: "请输入菜单名称" }],
  type: [{ required: true, message: "请选择类型" }],
  sort: [{ required: true, message: "请输入排序值" }],
});

const handleCreate = () => {
  Object.assign(form.value, {
    id: null,
    parentId: null, // 默认为顶级菜单
    title: "",
    vueHref: "",
    type: 0,
    vuePermission: "",
    sort: 0,
    inOrOutTable: 0,
    icon: "",
    remarks: "",
  });
  selectedIcon.value = "";
  showEditPopup.value = true;
};
 
const editRow = async (row: MenuNode) => {
  const res = await getDetailId("menu", { id: row.id });
  Object.assign(form.value, {
    id: res.id,
    parentId: res.parentId, // 直接赋值父级 id 给 VxeTreeSelect
    title: res.title || "",
    vueHref: res.vueHref || "",
    type: Number(res.type),
    vuePermission: res.vuePermission || "",
    sort: res.sort || 0,
    inOrOutTable: Number(res.inOrOutTable),
    icon: res.icon || "",
    remarks: res.remarks || "",
  });

  selectedIcon.value = form.value.icon;
  showEditPopup.value = true;
};

const confirmEvent = async () => {
  const $form = unref(formRef);
  const valid = await $form?.validate();
  if (!valid) {
    const {
      id,
      parentPath,
      parentId,
      title,
      inOrOutTable,
      vueHref,
      type,
      vuePermission,
      sort,
      remarks,
    } = form.value;

    const menuDataPayload = {
      id,
      title,
      vueHref,
      icon: form.value.icon || undefined,
      inOrOutTable: String(inOrOutTable),
      type: String(type),
      vuePermission,
      sort,
      parentId: id
        ? parentId
        : parentPath.length > 0
        ? parentPath[parentPath.length - 1]
        : null,
      select: parentId,
      remarks,
    }; 
    try {
      const node = await menuAdd(menuDataPayload);
      if (node.code == 0) {
        ElMessage.success(id ? "编辑成功" : "新增成功");
        await reloadMenuData();
      } else {
        ElMessage.error(node.message);
      }
      // 关闭弹窗
      showEditPopup.value = false;
    } catch (error) {
      ElMessage.error(id ? "编辑失败" : "新增失败");
    }
  }
};
const handleDelete = (row: RowVO) => {
  console.log(row)
  removeRow(String(row));
};
const removeRow = (id) => {
  VxeUI.modal.confirm({
    title: "提示",
    content: "确定删除数据吗？",
    mask: false,
    lockView: false,
    onConfirm: async () => {
      const res = await delEntityById("menu", { ids: id });
      if (res.code == 0) {
        ElMessage.success("删除成功");
        await reloadMenuData();
      } else {
        ElMessage.error(res.message);
      }
    },
  });
};

const addChildMenu = (parent: MenuNode) => {
  Object.assign(form.value, {
    id: null,
    parentId: parent.id,
    parentPath: getNodePathById(menuData.value, parent.id) || [],
    title: `子菜单${(parent.children?.length || 0) + 1}`,
    vueHref: "",
    type: 0,
    vuePermission: "",
    sort: 0,
    icon: "",
    remarks: "",
  });
  selectedIcon.value = "";
  showEditPopup.value = true;
};

const { getButtonIcon, handleRowAction } = useTableActions<RowVO>({
  customAction(row) {
    console.log("自定义操作:", row.name);
  },
});

const selectAllChangeEvent: VxeGridEvents.CheckboxAll<RowVO> = ({
  checked,
}) => {
  const $grid = gridRef.value;
  if ($grid) {
    const records = $grid.getCheckboxRecords();
    selectedRows.value = records as unknown as MenuNode[];
  }
};

const selectChangeEvent: VxeGridEvents.CheckboxChange<RowVO> = ({
  checked,
}) => {
  const $grid = gridRef.value;
  if ($grid) {
    const records = $grid.getCheckboxRecords();
    selectedRows.value = records as unknown as MenuNode[];
  }
};
const expandAllEvent = () => {
  const $grid = gridRef.value;
  if ($grid) {
    $grid.setAllTreeExpand(true);
  }
};

const clearExpandEvent = () => {
  const $grid = gridRef.value;
  if ($grid) {
    $grid.clearTreeExpand();
  }
};
const gridEvents: VxeGridListeners = {
  formSubmit({ data }) {
    reloadMenuData(data);
  },
  formReset() {
    reloadMenuData();
  },
  toolbarButtonClick(params) {
    if (params.code == "add") {
      handleCreate();
    } else if (params.code == "del") {
      if (selectedRows.value.length === 0) {
        ElMessage.warning("请先选择要删除的菜单");
        return;
      }
      const ids = selectedRows.value.map((row) => row.id).join(",");
      removeRow(ids);
    }
  },
};
</script>
<style lang="scss" scoped>
.menu-management {
  padding: 16px;
}

.box-card {
  margin-bottom: 16px;
}

.demo-form-inline :deep(.el-form-item) {
  margin-bottom: 0;
}

.table-main {
  :deep(.el-table) {
    margin-top: 16px;
  }
}

:deep(.el-cascader) {
  width: 100%;
}
</style>
